#include "Util/ResourcePool.h"
#include <gtest/gtest.h>
#include <thread>
#include <atomic>

// 测试用的简单资源类
class TestResource {
public:
    TestResource(int id) : id_(id) {}
    
    int getId() const { return id_; }
    void setValue(int value) { value_ = value; }
    int getValue() const { return value_; }
    
private:
    int id_;
    int value_ = 0;
};

class ResourcePoolTest : public ::testing::Test {
protected:
    static std::atomic<int> nextId;
    
    // 创建资源的函数
    static std::shared_ptr<TestResource> createResource() {
        return std::make_shared<TestResource>(nextId++);
    }
    
    // 验证资源的函数
    static bool validateResource(const std::shared_ptr<TestResource>& resource) {
        return resource && resource->getId() >= 0;
    }
};

std::atomic<int> ResourcePoolTest::nextId{0};

// 测试基本创建和获取
TEST_F(ResourcePoolTest, BasicAcquireAndRelease) {
    ResourcePool<TestResource> pool(createResource, validateResource);
    
    auto resource = pool.acquire();
    ASSERT_TRUE(resource != nullptr);
    
    int id = resource->getId();
    resource->setValue(42);
    
    pool.release(resource);
    
    // 再次获取应该得到同一个资源
    auto resource2 = pool.acquire();
    ASSERT_TRUE(resource2 != nullptr);
    EXPECT_EQ(id, resource2->getId());
    EXPECT_EQ(42, resource2->getValue());
    
    pool.release(resource2);
}

// 测试初始池大小
TEST_F(ResourcePoolTest, InitialSize) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 5;
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    
    EXPECT_EQ(5, pool.size());
    EXPECT_EQ(5, pool.availableCount());
    
    auto resources = std::vector<std::shared_ptr<TestResource>>();
    for (int i = 0; i < 5; ++i) {
        resources.push_back(pool.acquire());
        ASSERT_TRUE(resources.back() != nullptr);
    }
    
    EXPECT_EQ(5, pool.size());
    EXPECT_EQ(0, pool.availableCount());
    
    for (auto& res : resources) {
        pool.release(res);
    }
    
    EXPECT_EQ(5, pool.availableCount());
}

// 测试最大池大小和自动增长
TEST_F(ResourcePoolTest, MaxSizeAndGrowth) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 2;
    config.maxSize = 5;
    config.growOnDemand = true;
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    
    auto resources = std::vector<std::shared_ptr<TestResource>>();
    for (int i = 0; i < 5; ++i) {
        auto resource = pool.acquire(std::chrono::milliseconds(100)); // 添加超时
        ASSERT_TRUE(resource != nullptr);
        resources.push_back(resource);
    }
    
    EXPECT_EQ(5, pool.size());
    EXPECT_EQ(0, pool.availableCount());
    
    // 尝试获取超过最大大小的资源
    auto extraResource = pool.acquire(std::chrono::milliseconds(100)); // 添加超时
    EXPECT_TRUE(extraResource == nullptr);
    
    // 释放一个资源后应该可以再次获取
    pool.release(resources.back());
    resources.pop_back();
    
    extraResource = pool.acquire(std::chrono::milliseconds(100)); // 添加超时
    ASSERT_TRUE(extraResource != nullptr);
    resources.push_back(extraResource);
    
    for (auto& res : resources) {
        pool.release(res);
    }
}

// 测试资源验证
TEST_F(ResourcePoolTest, ResourceValidation) {
    bool validationCalled = false;
    
    auto validateFunc = [&validationCalled](const std::shared_ptr<TestResource>& resource) {
        validationCalled = true;
        return resource->getId() < 100; // 假设ID < 100的资源有效
    };
    
    ResourcePool<TestResource> pool(createResource, validateFunc);
    
    auto resource = pool.acquire();
    ASSERT_TRUE(resource != nullptr);
    
    validationCalled = false;
    pool.release(resource);
    
    auto resource2 = pool.acquire();
    ASSERT_TRUE(resource2 != nullptr);
    EXPECT_TRUE(validationCalled);
    
    pool.release(resource2);
}

// 测试清空池
TEST_F(ResourcePoolTest, ClearPool) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 5;
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    EXPECT_EQ(5, pool.size());
    
    pool.clear();
    EXPECT_EQ(0, pool.availableCount());
    
    // 清空后应该仍然可以获取资源（会创建新资源）
    auto resource = pool.acquire();
    ASSERT_TRUE(resource != nullptr);
    pool.release(resource);
}

// 测试调整池大小
TEST_F(ResourcePoolTest, ResizePool) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 3;
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    EXPECT_EQ(3, pool.size());
    
    // 增加大小
    pool.resize(5);
    EXPECT_EQ(5, pool.size());
    
    // 减小大小
    pool.resize(2);
    EXPECT_EQ(2, pool.availableCount());
}

// 测试超时
TEST_F(ResourcePoolTest, Timeout) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 1;
    config.maxSize = 1;
    config.growOnDemand = false;
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    
    auto resource = pool.acquire();
    ASSERT_TRUE(resource != nullptr);
    
    // 尝试获取资源，应该超时
    auto start = std::chrono::steady_clock::now();
    auto timeoutResource = pool.acquire(std::chrono::milliseconds(100));
    auto end = std::chrono::steady_clock::now();
    
    EXPECT_TRUE(timeoutResource == nullptr);
    auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
    EXPECT_GE(duration, 100);
    
    pool.release(resource);
}

// 测试多线程环境 TODO 暂时有问题
TEST_F(ResourcePoolTest, MultiThreaded) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 5;
    config.maxSize = 10;
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    
    std::vector<std::thread> threads;
    std::atomic<int> successCount{0};
    
    for (int i = 0; i < 20; ++i) {
        threads.emplace_back([&pool, &successCount]() {
            // 增加超时时间到 1000ms
            auto resource = pool.acquire(std::chrono::milliseconds(1000));
            if (resource) {
                successCount++;
                std::this_thread::sleep_for(std::chrono::milliseconds(50));
                pool.release(resource);
            }
        });
    }
    
    for (auto& t : threads) {
        t.join();
    }
    
    EXPECT_EQ(20, successCount);
    EXPECT_EQ(10, pool.size());
    EXPECT_EQ(10, pool.availableCount());
}

// 测试过期资源清理
TEST_F(ResourcePoolTest, ExpiredResourceCleanup) {
    ResourcePool<TestResource>::Config config;
    config.initialSize = 3;
    config.maxIdleTime = std::chrono::milliseconds(100);
    
    ResourcePool<TestResource> pool(createResource, validateResource, config);
    EXPECT_EQ(3, pool.availableCount());
    
    // 等待资源过期
    std::this_thread::sleep_for(std::chrono::milliseconds(200));
    
    // 获取资源会触发清理
    auto resource = pool.acquire();
    ASSERT_TRUE(resource != nullptr);
    
    // 应该只有一个资源在使用中，其他的都被清理了
    EXPECT_EQ(1, pool.size());
    EXPECT_EQ(0, pool.availableCount());
    
    pool.release(resource);
    EXPECT_EQ(1, pool.availableCount());
}

int main(int argc, char **argv) {
    ::testing::InitGoogleTest(&argc, argv);
    return RUN_ALL_TESTS();
}